﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data.SqlClient;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ZilLion.Service.Core.CRMUnities.Config;
using ZL.Web.Utility.SMSS;
using ZLWeb.WebApiEntityBas;
using ZLWeb.WebApiEntityBase;

namespace ZL.Web.Utility.Log
{
    public class ErrLogFileHelper
    {
        private static readonly int ErrInterval;
        private static readonly int SmssInterval;
        private static readonly string ServiceDisPlayName;

        public static Dictionary<string, ErrRelatedTime> ErrDictionary = new Dictionary<string, ErrRelatedTime>();


        static ErrLogFileHelper()
        {
            string errInterval = ConfigurationManager.AppSettings["ErrInterval"];
            string smssInterval = ConfigurationManager.AppSettings["SMSSInterval"];
            string serviceName = ConfigurationManager.AppSettings["ServiceDisPlayName"];

            ErrInterval = string.IsNullOrEmpty(errInterval)? 0: int.Parse(errInterval);
            SmssInterval = string.IsNullOrEmpty(smssInterval) ? 0 : int.Parse(smssInterval); 
            ServiceDisPlayName = string.IsNullOrEmpty(serviceName) ? "" : serviceName; 
        }

        public static void ErrHandle(Exception ex)
        {
            string errDesc = ex.Message;

            if (ErrDictionary.ContainsKey(errDesc))
            {
                var lastLogTime = ErrDictionary[errDesc].LastLogTime;
                var lastSmssTime = ErrDictionary[errDesc].LastSmsTime;

                TimeSpan smssTimeSpan = DateTime.Now - lastSmssTime;
                TimeSpan errTimeSpan = DateTime.Now - lastLogTime;

                //是否超过记错误日志的间隔时间
                if (errTimeSpan.TotalSeconds > ErrInterval)
                {
                    ErrDictionary[errDesc].LastLogTime = DateTime.Now;

                    //是否超过短信通知的间隔时间
                    if (smssTimeSpan.TotalSeconds > SmssInterval)
                    {
                        if (SendSms(errDesc))
                        {
                            Console.WriteLine("发送短信End...");
                            ErrDictionary[errDesc].LastSmsTime = DateTime.Now;
                        }
                    }
                    
                }

                ErrDictionary[errDesc].LastErrTime = DateTime.Now;
            }
            else
            {
                //首次加入ErrDic，若错误Dic已超过50，先删最后一次请求时间最小的
                if (ErrDictionary.Count > 50)
                {
                    var lastErrValue = ErrDictionary.Values.OrderBy(x => x.LastErrTime).FirstOrDefault();
                    var key = ErrDictionary.FirstOrDefault(x => x.Value == lastErrValue).Key;
                    ErrDictionary.Remove(key);

                }

                WriteLog(ex);
                ErrRelatedTime errRelatedTime = new ErrRelatedTime()
                {
                    LastErrTime = DateTime.Now,
                    LastLogTime = DateTime.Now,
                };

                //首次非服务连接错误则发短信
                if (!(ex.Message.Contains("无法连接")|| ex.Message.Contains("服务不通")))
                {
                    if (SendSms(errDesc))
                    {
                        Console.WriteLine("发送短信End...");
                        errRelatedTime.LastSmsTime = DateTime.Now;
                    }
                }

                ErrDictionary.Add(errDesc, errRelatedTime);
            }
        }


        /// <summary>
        /// 将异常打印到LOG文件
        /// </summary>
        /// <param name="ex">异常</param>
        /// <param name="LogAddress">日志文件地址</param>
        public static void WriteLog(Exception ex, string LogAddress = "", string desc = "")
        {
            //如果日志文件为空，则默认在Debug目录下新建 YYYY-mm-dd_Log.log文件
            if (LogAddress == "")
            {
                LogAddress = AppDomain.CurrentDomain.BaseDirectory + '\\' +
                    DateTime.Now.Year + '-' +
                    DateTime.Now.Month + '-' +
                    DateTime.Now.Day + "_Log.log";
            }

            //把异常信息输出到文件
            StreamWriter sw = new StreamWriter(LogAddress, true);
            sw.WriteLine("当前时间：" + DateTime.Now.ToString());
            sw.WriteLine("异常信息：" + ex.Message);
            sw.WriteLine("异常对象：" + ex.Source);
            sw.WriteLine("调用堆栈：\n" + ex.StackTrace.Trim());
            sw.WriteLine("触发方法：" + ex.TargetSite);
            if (!string.IsNullOrEmpty(desc))
            {
                sw.WriteLine("备注描述：" + desc);
            }
            
            sw.WriteLine();
            sw.Close();
        }


        private static bool SendSms(string exMessage)
        {
            Console.WriteLine("发送短信Begin...");
            ISmsService smsService = new SmsService();
            SmssContent smssContent = new SmssContent() { Content = $"程序名称:{ServiceDisPlayName}出现异常，错误描述（{exMessage}）" };

            ResponseResultInfo ret = smsService.SendMsg(smssContent);

            if (ret == null) return false;
            if (ret.DBCommitted && ret.Errormodel == null) return true;
            return false;
        }
    }




    public class ErrRelatedTime
    {
        //最后一次写日志的时间
        public DateTime LastLogTime { get; set; }
        //最后一次发生错误的时间
        public DateTime LastErrTime { get; set; }
        //最后一次发短信的时间
        public DateTime LastSmsTime { get; set; }

    }
}
